global generar_tabla_codigos

extern calloc
extern malloc
extern printf
extern free
extern crear_lista_huffman
extern crear_arbol_huffman
extern generar_codigo


;codigo_t * generar_tabla_codigos ( unsigned int *tabla_apariciones )

%define p_tabla_apar ebp+8
%define p_lista ebp-4
%define p_indices ebp-8
%define p_arbol  ebp-12
%define p_codigo ebp-16
%define max_elem 256
%define null 0
%define tam_codigo_t 16

section .data
msg_error_generar_codigo: db 'ERROR: La longitud de la codificacion es demasiado larga.',10,0


section .text
generar_tabla_codigos:
	;enter 16,0	; comentado para probar con valgrind
	push ebp
	mov ebp,esp
	sub esp,16
	
	push ebx
	push esi
	push edi

	; Incialializamos en null los punteros
	mov dword [p_lista],null
	mov dword [p_indices],null
	mov dword [p_arbol],null
	mov dword [p_codigo],null
	
	lea eax, [p_indices]
	push eax
	lea eax, [p_lista]
	push eax
	push dword [p_tabla_apar]
	call crear_lista_huffman
	add esp,12
	
	
	lea eax, [p_arbol]
	push eax
	lea eax, [p_lista]
	push eax
	call crear_arbol_huffman
	add esp,8
	
	
	mov esi,[p_indices]	; en esi ya tengo el puntero a la tabla de indices
		
	mov ebx,[p_arbol]	; en ebx ya tengo el puntero al arbol de huffman
	
		
; tengo que recorrer la lista tomando un nodo y pasandoselo a generar_codigo junto con el puntero al arbol
	
	push dword 16; pushe tamanio de elementos
	push dword max_elem
	call calloc 
	add esp,8
	
	mov [p_codigo], eax
	mov edx,eax ; pongo en edx el puntero a la tabla de codigos  
	
	xor ecx,ecx

_recorrerLista:
	cmp ecx,max_elem
	je fin
	
	mov edi, [esi+4*ecx]
	inc ecx
	
	cmp edi, null
	je _incrementar
	
	push ecx ; resguardo ecx
	push edx ; resguardo edx
	
	push edx
	push edi	
	push ebx
	call generar_codigo
	add esp,12

	
	
	cmp eax,-1
	je _error_generar_codigo
	
	pop edx ; recupero edx
	pop ecx ; recupero ecx
	
_incrementar:
	add edx,tam_codigo_t
	
	jmp _recorrerLista
	
_error_generar_codigo:
	cmp dword [p_codigo],null
	je _mostrar_mensaje
	; Si p_codigo tiene algo, no dejamos memoria colgada sin liberar
	push dword [p_codigo]
	call free
	add esp,4
	mov dword [p_codigo],null
	
_mostrar_mensaje:
	push dword msg_error_generar_codigo
	call printf
	add esp,4
		
fin:
	mov ebx, [p_lista]
	cmp ebx,null
	je _verificar_indices
	push ebx
	call _liberar_lista_arbol	; liberamos la lista
	add esp,4
	
_verificar_indices:
	mov ebx, [p_indices]
	cmp ebx, null
	je _verificar_arbol
	push ebx
	call free
	add esp,4
	
_verificar_arbol:
	mov ebx, [p_arbol]
	cmp ebx,null
	je _asignar_codigo
	
	push ebx
	call _liberar_arbol	; liberamos el arbol
	add esp,4

_asignar_codigo:

	mov eax, [p_codigo]  ;devolvemos el ptr al codigo
	

	pop edi
	pop esi
	pop ebx
	leave
	ret
	
; funcion recursiva (ojo)
;void liberar_arbol(nodo_arbol_t *arbol);
%define p_arbol_lib ebp+8
%define null 0
%define offset_izq 13
%define offset_der 17
_liberar_arbol:
	push ebp
	mov ebp,esp
	push ebx
	push esi
	push edi

	mov ebx, [p_arbol_lib]
	cmp ebx, null
	jne _lib_arb_no_null
	jmp _lib_arb_fin
_lib_arb_no_null:
	mov esi, [ebx+offset_izq]
	cmp esi, null
	je _lib_arb_ver_der
	push esi
	call _liberar_arbol	; liberamos recursivamente el arb. izq
	add esp,4
_lib_arb_ver_der:
	mov esi, [ebx+offset_der]
	cmp esi, null
	je _lib_arb_nodo_prin
	push esi
	call _liberar_arbol	; liberamos recursivamente el arb. der
	add esp,4
_lib_arb_nodo_prin:
	push ebx
	call free		; liberamos al nodo principal
	add esp,4
_lib_arb_fin:
	pop edi
	pop esi
	pop ebx
	leave
	ret

; funcion recursiva (ojo)
;void liberar_lista_arbol(nodo_lista_t *lista);
%define p_lista_lib ebp+8
%define null 0
%define nodo_arbol 0
%define sig 4
_liberar_lista_arbol:
	push ebp
	mov ebp,esp
	push ebx
	push esi
	push edi

	mov ebx, [p_lista_lib]
	cmp ebx, null
	jne _lib_list_no_null
	jmp _lib_list_fin

_lib_list_no_null:
	mov esi, [ebx+sig]
	cmp esi,null
	je _lib_list_ver_arbol
	push esi
	call _liberar_lista_arbol   ; liberamos recursivamente el siguiente
	add esp,4
_lib_list_ver_arbol:
	mov esi, [ebx+nodo_arbol]
	cmp esi,null
	je _lib_list_fin
	push esi
	call _liberar_arbol	; liberamos el arbol
	add esp,4

	push ebx
	call free	; liberamos el nodo principal
	add esp,4	
	
_lib_list_fin:
	
	pop edi
	pop esi
	pop ebx
	leave
	ret
	
